
/**
 * 1. 代理数据。数据 → 响应式数据
 * 2. 收集依赖
 * 3. 通过依赖修改DOM
 */

class MVVM {
  
  constructor(el, data) {
    this.el = document.querySelector(el);
    this.data = data;
    /**
     * 键值对
     * key: data中绑定的值，value：对应 {{ }} 绑定的数据。
     */
    this.domPool = {};
    this.init();
  }

  init() {
    // 代理数据
    this.initData();

    // 初始化DOM，包括收集依赖和通过依赖修改DOM
    this.initDom(this.el);
  }

  initData() {

    this.data = new Proxy(this.data, {
      get:(target, p) => {
        // console.log('获取数据, key: '+ p + ' value: ' + that._data[p]);
        return Reflect.get(target, p);
      },
      set: (target, p, newValue) => {
        // console.log('设置数据，key：'+ p + ' = ' + newValue);
        return Reflect.set(target, p, newValue) & this.handleDom(p);
      }
    })
  }

  initDom(el) {
    // 收集input的依赖，仅仅包括y-model
    this.bindInput(el);

    // 收集绑定依赖
    this.bindDom(el);
  }

  bindInput(el) {
    const _allInputs = el.querySelectorAll('input');
    _allInputs.forEach(input => {
      const yModel = input.getAttribute('y-model');

      if ( yModel ) {
        input.addEventListener('keyup', this.handleInput.bind(this, yModel, input));
      }
    });
  }
  
  handleInput(key, input) {
    const _value = input.value;
    this.data[key] = _value;
  }

  bindDom(el) {
    const childNodes = el.childNodes;

    childNodes.forEach(node => {
      if( node.nodeType == 3 ) {
        const _text = node.nodeValue;

        // 文本不为空
        if( _text.trim().length ) {
          let _isValid = /\{\{ (.+?) \}\}/.test(_text);

          // 存在 {{ }}
          if ( _isValid ) {
            const _key = _text.match(/\{\{(.+?)\}\}/)[1].trim();
            this.domPool[_key] = node.parentNode;
            this.handleDom(_key)
          } 
        }
      }
      node.childNodes && this.bindDom(node);
    })
  }

  handleDom(key) {
    this.domPool[key].innerHTML = this.data[key];
    return true;
  }
}